]> dgit.raspbian.org Git - gnome-shell.git/commitdiff
introspect: Add GetWindows method
authorOlivier Fourdan <ofourdan@redhat.com>
Wed, 12 Dec 2018 15:02:29 +0000 (16:02 +0100)
committerOlivier Fourdan <ofourdan@redhat.com>
Wed, 9 Jan 2019 09:13:45 +0000 (10:13 +0100)
The `GetWindows` method gives access to the list of windows for each
application with some of their properties, so utilities such as dogtail
can pick the window of their choice to interfere with using the provided
window id.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/326

data/dbus-interfaces/org.gnome.Shell.Introspect.xml
js/misc/introspect.js

index 10c48d635284950adf4f0663e9b04bf016caf7c9..9508681af1614b6f02b6c7153c3e757b58d21d6b 100644 (file)
     <method name="GetRunningApplications">
       <arg name="apps" direction="out" type="a{sa{sv}}" />
     </method>
+
+    <!--
+        GetWindows:
+        @short_description: Retrieves the current list of windows and their properties
+
+        A window is exposed as:
+        * t ID: unique ID of the window
+        * a{sv} properties: high-level properties
+
+          Known properties:
+
+          - "title"       (s): (readonly) title of the window
+          - "app-id"      (s): (readonly) application ID of the window
+          - "wm-class"    (s): (readonly) class of the window
+          - "client-type" (u): (readonly) 0 for Wayland, 1 for X11
+          - "is-hidden"   (b): (readonly) if the window is currently hidden
+          - "has-focus"   (b): (readonly) if the window currently have
+                                          keyboard focus
+          - "width"       (u): (readonly) width of the window
+          - "height"      (u): (readonly) height of the window
+    -->
+    <method name="GetWindows">
+      <arg name="windows" direction="out" type="a{ta{sv}}" />
+    </method>
   </interface>
 </node>
index fa0a66e006aa5a9bec1f37ce9b61a4cf163f207a..5599e1a66a758e9259a7b2e55cecfdb8999d4df0 100644 (file)
@@ -97,6 +97,17 @@ var IntrospectService = new Lang.Class({
         this._activeApplicationDirty = false;
     },
 
+    _isEligibleWindow(window) {
+        if (window.is_override_redirect())
+            return false;
+
+        let type = window.get_window_type();
+        return (type == Meta.WindowType.NORMAL ||
+                type == Meta.WindowType.DIALOG ||
+                type == Meta.WindowType.MODAL_DIALOG ||
+                type == Meta.WindowType.UTILITY);
+    },
+
     GetRunningApplicationsAsync(params, invocation) {
         if (!this._isIntrospectEnabled() &&
             !this._isSenderWhitelisted(invocation.get_sender())) {
@@ -107,5 +118,49 @@ var IntrospectService = new Lang.Class({
         }
 
         invocation.return_value(new GLib.Variant('(a{sa{sv}})', [this._runningApplications]));
+    },
+
+    GetWindowsAsync(params, invocation) {
+        let focusWindow = global.display.get_focus_window();
+        let apps = this._appSystem.get_running();
+        let windowsList = {};
+
+        if (!this._isIntrospectEnabled()) {
+            invocation.return_error_literal(Gio.DBusError,
+                                            Gio.DBusError.ACCESS_DENIED,
+                                            'App introspection not allowed');
+            return;
+        }
+
+        for (let app of apps) {
+            let windows = app.get_windows();
+            for (let window of windows) {
+
+                if (!this._isEligibleWindow(window))
+                    continue;
+
+                let windowId = window.get_id();
+                let frameRect = window.get_frame_rect();
+                let title = window.get_title();
+                let wmClass = window.get_wm_class();
+
+                windowsList[windowId] = {
+                    'app-id': GLib.Variant.new('s', app.get_id()),
+                    'client-type': GLib.Variant.new('u', window.get_client_type()),
+                    'is-hidden': GLib.Variant.new('b', window.is_hidden()),
+                    'has-focus': GLib.Variant.new('b', (window == focusWindow)),
+                    'width': GLib.Variant.new('u', frameRect.width),
+                    'height': GLib.Variant.new('u', frameRect.height)
+                };
+
+                // These properties may not be available for all windows:
+                if (title != null)
+                    windowsList[windowId]['title'] = GLib.Variant.new('s', title);
+
+                if (wmClass != null)
+                    windowsList[windowId]['wm-class'] = GLib.Variant.new('s', wmClass);
+            }
+        }
+        invocation.return_value(new GLib.Variant('(a{ta{sv}})', [windowsList]));
     }
 });